<template>
  <div class="app-container" v-loading="pageLoading">
    <div v-if="treeData.length == 0" class="filter-container">
      <el-button type="primary" @click="createNode(null)">新建菜单</el-button>
    </div>
    <div v-else class="filter-container">
      <el-input class="filter-item" style="width: 160px" clearable :placeholder="'请输入查询条件'" v-model="filterText">
      </el-input>
      <div class="filter-item text-gray t-12" v-if="!filterText">拖动菜单可调整层级和排序</div>
      <div class="flex1"></div>
      <div class="inlineBlock">
        <template v-if="indexChangeFlag">
          <el-button type="success" @click="saveIndex" :loading="sortLoading">保存排序 </el-button>
          <el-button type="warning" @click="
              () => {
                indexChangeFlag = false
                refreshTree()
              }
            ">取消
          </el-button>
        </template>
        <el-button type="primary" v-else @click="
            () => {
              currentExpands = []
              refreshTree()
            }
          ">
          刷新
        </el-button>
      </div>
    </div>
    <div style="border: #f4f4f4 solid 1px; padding: 10px 0">
      <el-tree ref="tree" :data="treeData" node-key="id" :default-expand-all="false" :expand-on-click-node="false"
        draggable :allow-drop="nodeIndexCheck" @node-drop="afterDrop" :filter-node-method="filterMethod"
        :defaultExpandedKeys="defaultExpandedKeys" @node-expand="nodeExpand" @node-collapse="nodeCollapse">
        <div class="custom-tree-node" slot-scope="{ data }">
          <div style="display: inline-block">
            <span class="text-label" :class="{
                'bg-blue': data.resource_type == 'MENU',
                'bg-green': data.resource_type == 'WEB',
                'bg-yellow': data.resource_type == 'WIN',
                'bg-red': data.resource_type == 'PDA',
              }">{{ data.resource_type }}</span>
            <span v-if="data.resource_type !='MENU'" class="ml-10">
              <span v-if="data.is_visible == 'Y'">
                <svg-icon style="color:#67C23A" icon-class="eye-open" />
              </span>
              <span v-else>
                <svg-icon style="color:#909399" icon-class="eye-close" />
              </span>
            </span>
            <span style="margin-left: 10px" class="text-bold">{{ data.menu_name }}</span>
            <span style="margin-left: 10px; font-weight: normal; color: #999999">{{ data.path }}</span>
          </div>
          <div style="display: inline-block">
            <a href="#" v-if="data.enabled" class="text-blue" title="已启用" style="font-size: 14px"
              @click.prevent="disableOrEnable(data)">
              <i class="el-icon-open"></i>
            </a>
            <a href="#" v-else class="text-gray" title="已禁用" style="font-size: 16px"
              @click.prevent="disableOrEnable(data)">
              <i class="el-icon-turn-off"></i>
            </a>
            &nbsp;&nbsp;&nbsp;&nbsp;
            <a href="#" class="text-blue" @click.prevent="editNode(data)" title="编辑">编辑</a>&nbsp;
            <a href="#" class="text-green pl-5" @click.prevent="createNode(data)" title="创建平级">创建平级</a>&nbsp;
            <a href="#" class="text-yellow pl-5" @click.prevent="createChildNode(data)" title="创建下级">{{
              data.resource_type == 'MENU' ? '创建下级' : '　　　　'
            }}</a>&nbsp;
            <a href="#" class="text-red pl-5" v-permission="'adminMenu.delete'" @click.prevent="removeNode(data)"
              title="删除">删除</a>
          </div>
        </div>
      </el-tree>
    </div>
    <z-form-dialog :name="name" :data="data" :formProps="formProps" :fields="fields" @submit="submitNode"
      :submitLoading="submitLoading" :visible.sync="editFormVisible">
      <template v-slot:extra-area v-if="data.resource_type === 'WEB'">
        <div class="menuTable mb-10 ml-90">
          <el-button type="primary" v-if="!data.tableList.length" @click="columnsOperate(1)">添加表头</el-button>
          <z-table v-else :list="[]" :tableProps="{hideOperations:true,border:true}" :columns="data.tableList"
            ref="elTable" @header-dragend="headerDragend">
            <template v-slot:header="scope">
              <div :class="['flex','flex-col-between',{'text-224':data.tableList[scope.$index]['is_visible'] === 0}]"
                @click="columnsEdit(scope)">
                <span>标题:<span>{{scope.column.label}}</span></span><span>值:<span>{{scope.column.property}}</span></span><span
                  class="t-15">
                  <el-tooltip effect="dark" content="添加列" placement="top"><i
                      class="el-icon-circle-plus-outline text-bold text-green mr-10 pointer"
                      @click.stop="columnsOperate(1,scope.$index)"></i></el-tooltip><el-tooltip effect="dark"
                    content="删除列"><i class="el-icon-delete text-bold text-red pointer"
                      @click.stop="columnsOperate(0,scope.$index)"></i></el-tooltip></span>
              </div>
            </template>
          </z-table>
        </div>
      </template>
    </z-form-dialog>
    <z-form-dialog name="" :data="columnData" :formProps="{...formProps,title:columnData.dialogTitle}"
      :fields="columnFields" @submit="columnSubmit" :visible.sync="columnEditFormVisible"></z-form-dialog>
  </div>
</template>

<script>
import { generateTree, expendsTree, dateTools } from '@/utils'
import commonMixin from '@/views/_common/mixin'
import Sortable from 'sortablejs'
export default {
  mixins: [commonMixin],
  components: {},
  name: 'adminMenu',
  data: function () {
    return {
      name: '菜单',
      api: this.$api.menu,
      sortLoading: false,
      initData: {
        parent_id: '0',
        enabled: true,
        menu_seq: 9999,
        is_visible: true, //新增需求 是否开启
        tableList: [],
      },
      currentDataId: 0,
      treeData: [],
      fields: [
        {
          title: '类型',
          key: 'resource_type',
          required: true,
          name: 'select',
          options: [
            { label: '目录', value: 'MENU' },
            { label: 'Web功能', value: 'WEB' },
            { label: 'PDA功能', value: 'PDA' },
            { label: 'Client端功能', value: 'WIN' },
          ],
          events: {
            change: (e) => {
              if (e == 'WEB') {
                this.fields.forEach((el) => {
                  if (el.key == 'is_visible' || el.key == 'pagePermission') el.hidden = false
                })
              } else {
                this.fields.forEach((el) => {
                  if (el.key == 'is_visible' || el.key == 'pagePermission') el.hidden = true
                })
              }
              this.initSortable()
            },
          },
        },
        { title: '菜单名称', key: 'menu_name', required: true },
        {
          title: '页面权限',
          key: 'pagePermission',
          name: 'select',
          props: { multiple: true },
          required: true,
          options: [],
          tips: '如果页面已做到按钮级管控，选择对应的操作权限；如果没有请选择默认；如不确定请先与前端确认。',
          hidden: true,
        },
        { title: '菜单描述', key: 'menu_desc' },
        { title: '菜单路径', key: 'path' },

        { title: '图标', key: 'icon', tips: '类型为目录填写，支持fontawesome，如fa-home', disabled: false },
        { title: '是否可见', key: 'is_visible', name: 'switch', hidden: true },
      ],
      indexChangeFlag: false,
      filterText: '',
      defaultExpandedKeys: [],
      currentExpands: [],
      columnFields: [
        { title: '标题', key: 'title', required: true },
        { title: '值', key: 'key', required: true },
        { title: '宽度', key: 'width', name: 'number', props: { min: 0 }, tips: '小于 30 宽度自适应' },
        {
          title: '是否可见',
          key: 'is_visible',
          name: 'switch',
          props: {
            activeValue: 1,
            inactiveValue: 0,
          },
        },
      ],
      columnEditFormVisible: false,
      columnData: {},
      initColumnData: {
        is_visible: 1,
      },
    }
  },
  methods: {
    formatAfterGet(data) {
      let tmp = _.cloneDeep(data)
      return {
        ...tmp,
        tableList: tmp.tableList && tmp.tableList.length ? tmp.tableList : this.initData.tableList,
      }
    },
    initSortable() {
      if (!this.data.tableList.length) return
      if (this.data.resource_type !== 'WEB') return
      this.$nextTick(() => {
        let elT = this.$refs.elTable.$refs.elTable.$el.querySelector('table thead tr')
        new Sortable(elT, {
          animation: 150,
          onStart: (evt) => {},
          onEnd: ({ oldIndex, newIndex }) => {
            if (oldIndex === newIndex) return
            this.data.tableList.splice(newIndex, 0, this.data.tableList.splice(oldIndex, 1)[0])
            let newArray = this.data.tableList.slice(0)
            this.data.tableList = []
            this.$nextTick(function () {
              this.data.tableList = newArray
              this.initSortable()
            })
          },
        })
      })
    },
    columnsOperate(status, index) {
      if (status) {
        this.columnsEdit({ title: '', width: '', key: '', index: index, status: status })
      } else {
        this.data.tableList.splice(index, 1)
        if (this.data.tableList.length == 1) {
          this.data.tableList[0].width = ''
        }
      }
      if (!this.data.tableList.length) return
      this.initSortable()
      this.$nextTick(() => {
        this.$refs.elTable.$refs.elTable.doLayout()
        if (this.data.tableList.length > 1) return
        this.$refs.elTable.$refs.elTable.$el.querySelector('table').style.minWidth = '100%'
        this.$refs.elTable.$refs.elTable.$el.querySelector('.el-table__empty-block').style.minWidth = '100%'
      })
    },
    headerDragend({ newWidth, oldWidth, column, event }) {
      this.data.tableList = this.data.tableList.map((v) => {
        if (column.property === v.key) {
          v.width = newWidth
        }
        return v
      })
      this.$nextTick(() => {
        this.$refs.elTable.$refs.elTable.doLayout()
        this.initSortable()
      })
    },
    isNum(text) {
      let reg = /^[+-]?\d*(\.\d*)?(e[+-]?\d+)?$/
      return reg.test(text) ? '' : text
    },
    isRepeat(arr, data, ...rest) {
      return arr.reduce((prev, item) => {
        rest.forEach((v) => {
          if (item[v] == data[v]) {
            prev.push(item)
          }
        })
        return prev
      }, [])
    },
    columnsEdit(scope) {
      let data = {}
      if (scope.$index !== null && scope.$index !== undefined) {
        data = { ...this.data.tableList[scope.$index], index: scope.$index, status: 0, dialogTitle: '编辑' }
      } else {
        data = { ...scope, dialogTitle: '创建' }
      }
      let tmp = _.cloneDeep(data)
      this.columnData = { ...this.initColumnData, ...tmp, width: tmp.width < 30 ? '' : tmp.width }
      this.columnEditFormVisible = true
    },
    columnSubmit() {
      let tmp = _.cloneDeep(this.columnData)
      tmp.width = tmp.width < 30 ? '' : tmp.width
      let check = this.validataData(this.columnFields, tmp)
      if (!check) return
      if (!this.isNum(tmp.key)) return this.$message.error('值不能为纯数字')
      if (this.isRepeat(this.data.tableList, tmp, 'key', 'title').length && tmp.status) {
        return this.$message.error('已有相同的标题或值')
      }
      if (!tmp.status) {
        this.$set(this.data.tableList, tmp.index, tmp)
      } else {
        this.data.tableList.length ? this.data.tableList.splice(tmp.index + 1, 0, tmp) : this.data.tableList.push(tmp)
      }
      this.columnEditFormVisible = false
      this.initSortable()
      this.$nextTick(() => {
        this.$refs.elTable.$refs.elTable.doLayout()
        if (this.data.tableList.length > 1) return
        this.$refs.elTable.$refs.elTable.$el.querySelector('table').style.minWidth = '100%'
        this.$refs.elTable.$refs.elTable.$el.querySelector('.el-table__empty-block').style.minWidth = '100%'
      })
    },
    getList() {
      this.refreshTree()
    },
    research() {},
    editNode: function (data) {
      // 需求增加，编辑时除去 MENU resource_type 时，不展示
      if (data.resource_type != 'MENU') {
        for (let i = 0; i < this.fields.length; i++) {
          if (this.fields[i].key == 'is_visible' || this.fields[i].key == 'pagePermission')
            this.fields[i].hidden = false
        }
      } else {
        for (let i = 0; i < this.fields.length; i++) {
          if (this.fields[i].key == 'pagePermission' || this.fields[i].key == 'is_visible') this.fields[i].hidden = true
        }
      }
      this.pageLoading = true
      this.$request(this.api + 'getbyid', { id: data.id })
        .then((r) => {
          r['pagePermission'] = r.power_codes ? r.power_codes.split(',') : []
          r['is_visible'] = r.is_visible == 'Y' ? true : false
          this.data = this.formatAfterGet(r)
          this.initSortable()
        })
        .finally(() => {
          this.pageLoading = false
        })
      this.editFormVisible = true
    },
    createNode: function (data) {
      let initData = _.cloneDeep(this.initData)
      if (data) {
        this.data = { ...initData, parent_id: data.parent_id }
      } else {
        this.data = { ...initData }
      }
      this.editFormVisible = true
    },
    createChildNode: function (data) {
      if (data.resource_type != 'MENU') {
        return
      }
      let initData = _.cloneDeep(this.initData)
      this.data = { ...initData, parent_id: data.id }
      this.editFormVisible = true
    },
    submitNode: function () {
      let url = this.api + 'save'
      let data = Object.assign({}, this.data)

      let check = this.validataData(this.fields, data)
      if (!check) return
      if (data.children && data.children.length > 0 && data.resource_type != 'MENU') {
        this.$message.error('有下级存在，类型必须为目录')
        return
      }
      delete data.children
      data.is_visible ? (data.is_visible = 'Y') : (data.is_visible = 'N')
      // data = this.formatBeforeSave(this.data)
      data = this.formatBeforeSave(data)
      this.submitLoading = true
      this.$request(url, data, 'post')
        .then((r) => {
          this.submitLoading = false
          this.$message.success('操作成功')
          this.editFormVisible = false
          this.refreshTree()
        })
        .catch(() => {
          this.submitLoading = false
        })
    },
    formatBeforeSave(data) {
      //依据实际需求处理
      let tmp = _.cloneDeep(data)
      if (!!tmp.pagePermission) {
        tmp['power_codes'] = tmp.pagePermission.join(',')
      }
      delete tmp.pagePermission
      return tmp
    },
    disableOrEnable: function (data) {
      var enabled = !data.enabled
      this.pageLoading = true
      this.$request(this.api + 'save', { id: data.id, enabled }, 'post')
        .then((r) => {
          this.pageLoading = false
          this.$message({
            message: '操作成功',
            type: 'success',
          })
          data.enabled = enabled
        })
        .catch(() => {
          this.pageLoading = false
        })
    },
    removeNode: function (data) {
      this.$confirm('确定要删除这条记录？', '操作确认').then(() => {
        this.pageLoading = true
        this.$request(this.api + 'delete/' + data.id, {}, 'post')
          .then((r) => {
            this.pageLoading = false
            this.$message({
              message: '操作成功',
              type: 'success',
            })
            this.refreshTree()
          })
          .catch(() => {
            this.pageLoading = false
          })
      })
    },
    saveIndex: function () {
      var tmp = expendsTree(this.treeData)
      console.log(this.treeData, 'this.treeData')
      var data = []
      for (let i in tmp) {
        data.push({
          id: tmp[i].id,
          parent_id: tmp[i].parent_id,
          menu_seq: i,
        })
      }
      this.sortLoading = true
      let url = this.api + 'sort'
      this.$request(url, data, 'post')
        .then((r) => {
          this.sortLoading = false
          this.$message.success('操作成功')
          this.indexChangeFlag = false
          this.refreshTree()
        })
        .catch(() => {
          this.sortLoading = false
        })
    },
    nodeExpand(data) {
      console.log(data)
      this.currentExpands.push(data.id)
    },
    nodeCollapse(data) {
      console.log(data)
      let i = this.currentExpands.findIndex((x) => x == data.id)
      if (i != -1) this.currentExpands.splice(i, 1)
    },
    nodeIndexCheck: function (draggingNode, dropNode, type) {
      //同级的两个目录禁止拖动进去
      if (
        draggingNode.data.resource_type == 'MENU' &&
        dropNode.data.resource_type == 'MENU' &&
        dropNode.data.parent_id == draggingNode.data.parent_id
      ) {
        return type != 'inner'
      }
      //目标节点不是目录的禁止拖动进去
      if (dropNode.data.resource_type != 'MENU') {
        return type != 'inner'
      }
      return true
    },
    afterDrop: function (i, j, type) {
      if (type == 'inner') {
        i.data.parent_id = j.data.id
      } else {
        i.data.parent_id = j.data.parent_id
      }
      this.indexChangeFlag = true
    },
    filterMethod(value, data) {
      if (!value) return true
      return data.menu_name.includes(value)
    },
    refreshTree() {
      this.pageLoading = true
      this.$request(this.api + 'listForEdit', this.query)
        .then((r) => {
          this.treeData = generateTree(r, 'id', 'parent_id', '0')
          this.defaultExpandedKeys = this.currentExpands
        })
        .finally(() => {
          this.pageLoading = false
        })
    },
  },
  created: function () {
    this.getList()
    this.$request(this.$api.dictionary + 'getdirectchildren', {
      parentType: 'page_permission',
    }).then((r) => {
      this.getFieldConfig('pagePermission').options = this.arrayOptions(r, 'value', 'label')
    })
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    },
    data: function (val) {},
  },
}
</script>

<style scoped lang="scss">
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  padding-right: 8px;
}
::v-deep .text-224 {
  color: rgb(224, 224, 224, 0.8);
}
</style>
